<template>
  <div style="width: 100%;">
    <el-table :data="tableData" :height="tableHeight" style="width: 100%; margin-bottom: 20px;" row-key="id" border
      ref="tableRef" row-class-name="tableRowClass" default-expand-all @row-click="rowClick">
      <el-table-column prop="task" label="任务" show-overflow-tooltip width="300" fixed />
      <el-table-column prop="person" label="负责人" show-overflow-tooltip width="300" fixed />
      <el-table-column prop="note" label="备注" show-overflow-tooltip width="150" fixed />
      <template v-for="(item, index) in monthList">
        <el-table-column :label="item.year + '年' + item.month + '月'" width="150" :resizable="false"
          class-name="yearMonthClass">
          <template v-for="(item2, index2) in item.days">
            <el-table-column :label="item2 + ''" :width="dayWeight" align="center" class-name="dayClass"
              :resizable="false">
              <template #default="scope">
                <template v-if="scope.row.lev != 1">
                    <template v-if="scope.row.planStartTime == (item.year + '-' + item.month + '-' + (item2 < 10 ? '0' + item2 : item2))">
                      <div class="divYellow" @click="handClick(scope.row, '1', $event)"
                        :style="{ width: calculateDateDifference(scope.row.planStartTime, scope.row.planEndTime) + 'px!important' }">
                        {{ scope.row.planContent }}
                      </div>
                    </template>
                  <div v-else class="divNone">
                  </div>
                    <template v-if="scope.row.realStartTime == (item.year + '-' + item.month + '-' + (item2 < 10 ? '0' + item2 : item2))">
                      <div class="divOrange" @click="handClick(scope.row, '2', $event)"
                        :style="{ width: calculateDateDifference(scope.row.realStartTime, scope.row.realEndTime) + 'px!important' }">
                        {{ scope.row.realContent }}
                      </div>
                    </template>
                  <div v-else class="divNone">
                  </div>
                  <div class="divNone">
                  </div>
                </template>
              </template>
            </el-table-column>
          </template>
        </el-table-column>
      </template>
    </el-table>
  </div>
</template>

<script setup>
import { onMounted, ref, nextTick } from 'vue'

onMounted(() => {
  const scrollBarRef = tableRef.value?.$refs.scrollBarRef;
  const wrapRef = scrollBarRef.wrapRef;
  if ("onscrollend" in window) {
    // 年月文字跟随滚动条平移
    wrapRef.addEventListener("scroll", (event) => {
      const tableScrollLeft = event.target.scrollLeft;
      const yearMonthElement = document.querySelectorAll('.yearMonthClass');
      const whereIN = getScrollWhere(widthArr, tableScrollLeft);
      let i = 0;
      yearMonthElement.forEach(item => {
        const cellElement = item.querySelector('.cell');
        cellElement.style.top = 13 + "px";
        if (i == whereIN) {
          cellElement.style.position = 'absolute';
          cellElement.style.whiteSpace = 'nowrap';
          if (i == 0) {
            cellElement.style.left = tableScrollLeft + 'px';
          } else {
            cellElement.style.left = Math.abs(widthArr[whereIN - 1] - tableScrollLeft) + 'px';
          }
        } else {
          cellElement.style.position = 'static';
          cellElement.style.left = '0px';
        }
        i++;
      })
    });
  }
})


const tableRef = ref()
const tableHeight = window.innerHeight - 100;
// 日 列的宽度
const dayWeight = 50

const tableData = [
  {
    id: 3,
    task: '会前',
    person: '',
    note: '',
    lev: 1,
    children: [
      {
        id: 31,
        task: '会议创建',
        person: '王冰冰，张三',
        note: '备注11111111111111111111',
        planStartTime: '2023-08-01',
        planEndTime: '2023-08-29',
        realStartTime: '2023-08-03',
        realEndTime: '2023-08-31',
        planContent: '计划内容',
        realContent: '实际内容',
      },
      {
        id: 32,
        task: '会议网站信息录入',
        person: '冯海',
        note: '',
        planStartTime: '2023-09-02',
        planEndTime: '2023-09-05',
        planContent: '计划内容',
        realContent: '实际内容',
      },
    ],
  },
  {
    id: 4,
    task: '会中',
    person: '',
    note: '',
    lev: 1,
    children: [
      {
        id: 41,
        task: '会议创建',
        person: '王冰冰，张三',
        note: '备注11111111111111111111',
        planStartTime: '2023-08-06',
        planEndTime: '2023-08-08',
        realStartTime: '2023-08-09',
        realEndTime: '2023-08-11',
        planContent: '计划内容',
        realContent: '实际内容',
      },
      {
        id: 42,
        task: '会议网站信息录入',
        person: '冯海',
        note: '',
        planStartTime: '2023-08-17',
        planEndTime: '2023-08-18',
        realStartTime: '2023-08-15',
        realEndTime: '2023-10-01',
        planContent: '计划内容',
        realContent: '实际内容',
      },
    ]
  },
  {
    id: 5,
    task: '会后',
    person: '',
    note: '',
    lev: 1,
    children: []
  },
]

// 把所有参与到的日期放入数组中
let dateArr = [];
for (let i = 0; i < tableData.length; i++) {
  tableData[i]?.children?.forEach(item => {
    if (item.planStartTime) {
      dateArr.push(item.planStartTime)
    }
    if (item.planEndTime) {
      dateArr.push(item.planEndTime)
    }
    if (item.realStartTime) {
      dateArr.push(item.realStartTime)
    }
    if (item.realEndTime) {
      dateArr.push(item.realEndTime)
    }
  })
}
console.log(dateArr)
// 将日期字符串转换为 Date 对象
let dateObjects = dateArr.map(function (dateString) {
  return new Date(dateString);
});
// 计算最早和最晚的日期
let earliestDate = new Date(Math.min.apply(null, dateObjects));
let latestDate = new Date(Math.max.apply(null, dateObjects));

// 今天的当年当月1号
function getFirstDayOfMonth(type) {
  const myDate = new Date();
  const tYear = myDate.getFullYear();
  let tMonth = myDate.getMonth();
  tMonth = doHandleZero(tMonth + 1);
  if (type == 1) {
    return new Date(tYear + "-" + tMonth + "-01");
  } else {
    return new Date(tYear + "-" + tMonth + "-28");
  }
}
// 还没数据的时候给默认当前年当前月
if (earliestDate.toDateString() == "Invalid Date") {
  earliestDate = getFirstDayOfMonth(1);
}
if (latestDate.toDateString() == "Invalid Date") {
  latestDate = getFirstDayOfMonth(2);
}
console.log("最早的日期是：" + earliestDate.toDateString());
console.log("最晚的日期是：" + latestDate.toDateString());

//补0函数
function doHandleZero(zero) {
  let date = zero;
  if (zero.toString().length == 1) {
    date = "0" + zero;
    return date;
  }
  return zero;
}

// 使用最早日期，和最晚日期，获取跨度哪几年哪几个月，这年这月有多少天
function getMonthList(startDate, endDate) {
  const startYear = startDate.getFullYear();
  const startMonth = startDate.getMonth();
  const endYear = endDate.getFullYear();
  const endMonth = endDate.getMonth();
  const monthList = [];
  const totalMonths = (endYear - startYear) * 12 + (endMonth - startMonth) + 1;
  for (let i = 0; i < totalMonths; i++) {
    // 相隔年数
    const currentYear = startYear + Math.floor((startMonth + i) / 12);
    // 相隔月
    const currentMonth = (startMonth + i) % 12;
    // 这些相隔年月有多少天
    const daysInMonth = new Date(currentYear, currentMonth + 1, 0).getDate();
    monthList.push({
      year: currentYear,
      month: (currentMonth + 1) < 10 ? '0' + (currentMonth + 1) : (currentMonth + 1), // 月份从1开始
      days: daysInMonth,
      width: daysInMonth * dayWeight
    });
  }
  return monthList;
}
let monthList = getMonthList(earliestDate, latestDate);
let widthArr = [];
let baseWidth = 0;
monthList.forEach(item => {
  baseWidth += item.width
  widthArr.push(baseWidth);
})
console.log(widthArr)

// 获取当前滚动到哪个月区间了
function getScrollWhere(widthArr, scrolWidthLeft) {
  for (let i = 0; i < widthArr.length; i++) {
    if (i == 0 && scrolWidthLeft <= widthArr[0]) {
      return 0;
    }
    if (i == widthArr.length - 1) {
      return i;
    }
    if (scrolWidthLeft >= widthArr[i] && scrolWidthLeft <= widthArr[i + 1]) {
      return i + 1;
    }
  }
}

// 结束日期减去开始日期的相差天数 * 每日表格的宽度 dayWeight ，计算div需要的宽度
function calculateDateDifference(startDateStr, endDateStr, type = 1) {
  // 将日期字符串转换为 Date 对象
  const startDate = new Date(startDateStr);
  const endDate = new Date(endDateStr);
  // 计算毫秒差异
  const timeDiff = endDate.getTime() - startDate.getTime();
  // 将毫秒差异转换为天数差异
  const dayDiff = Math.ceil(timeDiff / (1000 * 3600 * 24));
  if (type == 2) {
    return (dayDiff - 1) * dayWeight;
  }
  return (dayDiff + 1) * dayWeight;
}

// 获取数据中最早一天的当年当月1号
function getThisDateFirstDate(date) {
  const month = date.getMonth() + 1;
  const year = date.getFullYear();
  const day = "01";
  return year + "/" + month + "/" + day;
}

// 行点击事件
const rowClick = (row, column, event) => {
  let scrolWidth = 0;
  if (row.planStartTime && row.realStartTime) {//如果两时间都存在，比大小
    let max = new Date(row.planStartTime).getTime() > new Date(row.realStartTime).getTime() ? row.realStartTime : row.planStartTime;
    scrolWidth = calculateDateDifference(getThisDateFirstDate(earliestDate), max, 2)
  } else if (row.planStartTime) {
    scrolWidth = calculateDateDifference(getThisDateFirstDate(earliestDate), row.planStartTime, 2)
  } else if (row.realStartTime) {
    scrolWidth = calculateDateDifference(getThisDateFirstDate(earliestDate), row.realStartTime, 2)
  }
  tableRef.value?.setScrollLeft(scrolWidth);
}

// 计划和实际任务，点击事件,type=1 计划 type=2 实际
const handClick = (row, type, event) => {
  console.log(row, type)
  console.log(event)
  event.stopPropagation();
}


</script>

<style>
.dayClass .cell {
  padding: 0 !important;
}

.divYellow {
  z-index: 2;
  cursor: pointer;
  height: 20px;
  background-color: yellow;
  position: absolute;
  border-radius: 4px;
}

.divNone {
  height: 30px;
}

.divOrange {
  z-index: 2;
  cursor: pointer;
  margin-top: 10px;
  height: 20px;
  background-color: orange;
  position: absolute;
  border-radius: 4px;
}

.el-table__body tr.hover-row>td.el-table__cell.dayClass {
  background-color: transparent !important;
}

.el-table .el-table__cell {
  z-index: unset !important;
  ;
}

.el-table__body-wrapper tr td.el-table-fixed-column--left,
.el-table__body-wrapper tr td.el-table-fixed-column--right,
.el-table__body-wrapper tr th.el-table-fixed-column--left,
.el-table__body-wrapper tr th.el-table-fixed-column--right,
.el-table__footer-wrapper tr td.el-table-fixed-column--left,
.el-table__footer-wrapper tr td.el-table-fixed-column--right,
.el-table__footer-wrapper tr th.el-table-fixed-column--left,
.el-table__footer-wrapper tr th.el-table-fixed-column--right,
.el-table__header-wrapper tr td.el-table-fixed-column--left,
.el-table__header-wrapper tr td.el-table-fixed-column--right,
.el-table__header-wrapper tr th.el-table-fixed-column--left,
.el-table__header-wrapper tr th.el-table-fixed-column--right {
  z-index: calc(var(--el-table-index) + 2) !important;
}

.el-popper {
  z-index: 2 !important;
}

.yearMonthClass {
  height: 50px !important;
}
</style>
